/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package importExportDat;

import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import strukturaRozpis.Rozpis;
import strukturaRozpis.Sluzba;
import strukturaSviatky.Sviatky;
import strukturaSviatky.Sviatok;
import strukturaZamestnanciNepritomnost.Zamestnanci;
import strukturaZamestnanciNepritomnost.Zamestnanec;

/**
 *
 * @author Ondrej
 */
public class ImportExportCSV {

    final String[] VRATNICE = {"M", "F"};
    final String DATE_FORMAT = "dd.MM.yyyy";
    final String HOUR_FORMAT = "HH:mm";  // 24h
    final String[] DAYS_OF_WEEK = {"Nedela", "Pondelok", "Utorok", "Streda", "Stvrtok", "Piatok", "Sobota"};
    final String[] MONTHS = {"januar", "februar", "marec", "april", "maj", "jun", "jul", "august", "september", "oktober", "november", "december"};
    final int POCET_SLUZIEB_ZA_DEN = 2;
    final String[] TYP_ZAMESTNANCA = {"vratnik", "straznik"};
    JFrame window = null; // aby som mal kam vyhadzovat chyby

    public ImportExportCSV() {
    }

    public ImportExportCSV(JFrame frame) {
        this.window = frame;
    }

    /**
     *
     * @param subor
     * @return
     */
    public boolean importZamestnanci(String subor) throws SQLException, ParseException {
        TreeMap<Integer, Zamestnanec> result = new TreeMap<>();
        Zamestnanci zams = new Zamestnanci();
        try {
            CsvReader zamestnanci = new CsvReader(subor, ';');

            zamestnanci.readHeaders();

            int riadok = 1;
            while (zamestnanci.readRecord()) {
                riadok++;
                int id;
                try {
                    id = zamestnanci.get("id").trim().equals("") ? -1 : Integer.valueOf(zamestnanci.get("id").trim());
                } catch (NumberFormatException e) {
                    JOptionPane.showMessageDialog(window, "Neplatné ID zamestnanca na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                String meno = zamestnanci.get("meno").trim();
                if ("".equals(meno)) {
                    JOptionPane.showMessageDialog(window, "Neplatné meno zamestnanca na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }
                String priezvisko = zamestnanci.get("priezvisko").trim();
                if ("".equals(priezvisko)) {
                    JOptionPane.showMessageDialog(window, "Neplatné priezvisko zamestnanca na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                String typ = zamestnanci.get("typ").trim();
                if (!typ.equals(TYP_ZAMESTNANCA[0]) && !typ.equals(TYP_ZAMESTNANCA[1])) {
                    JOptionPane.showMessageDialog(window, "Neplatný typ zamestnanca na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }
                int typ_zam = -1;
                for (int i = 0; i < TYP_ZAMESTNANCA.length; i++) {
                    if (typ.equals(TYP_ZAMESTNANCA[i])) {
                        typ_zam = i;
                        break;
                    }
                }

//                double pocetHodin;
//                try {
//                    pocetHodin = Double.valueOf(zamestnanci.get("pocet hodin").trim());
//                } catch (NumberFormatException e) {
//                    JOptionPane.showMessageDialog(window, "Neplatný počet hodín zamestnanca na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
//                    return false;
//                }

                double vahovanie = 0;
                try {
                    vahovanie = Double.valueOf(zamestnanci.get("vahovanie").trim());
                } catch (NumberFormatException e) {
                    JOptionPane.showMessageDialog(window, "Neplatné váhovanie zamestnanca na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                double dovolenka;
                try {
                    dovolenka = Double.valueOf(zamestnanci.get("pocet dni dovolenky").trim());
                } catch (NumberFormatException e) {
                    JOptionPane.showMessageDialog(window, "Neplatný počet dní dovolenky zamestnanca na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                Zamestnanec zam = new Zamestnanec(meno, priezvisko, vahovanie, dovolenka, typ_zam);
                if (id == -1) { // ak nebolo zadane id, pridaj priamo noveho zamestnanca
                    zams.addZamestnanec(zam);
                    result.put(getIDzamestnanca(meno + " " + priezvisko, zams), zam);
                } else {
                    result.put(id, zam);
                }
            }

            zamestnanci.close();

            // synch s databazou

            for (Map.Entry<Integer, Zamestnanec> elem : result.entrySet()) {
                Zamestnanec tmp = zams.getZamestnanciActive().get(elem.getKey());
                if (tmp == null) { // este taky neexistuje
                    zams.addZamestnanec(elem.getValue());
                } else { // ak existuje, edituj ho
                    zams.editZamestnanec(elem.getKey(), elem.getValue());
                }
            }
            ArrayList<Integer> coVymazat = new ArrayList<>();
            for (Map.Entry<Integer, Zamestnanec> elem : zams.getZamestnanciActive().entrySet()) {
                if (result.get(elem.getKey()) == null) {
                    coVymazat.add(elem.getKey());
                }
            }
            for (Integer elem : coVymazat) {
                zams.removeZamestnanec(elem);
            }

        } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(window, "Súbor sa nenašiel !", "Chyba", JOptionPane.ERROR_MESSAGE);
            return false;
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    public boolean isValidDate(String inDate) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);

        dateFormat.setLenient(false);
        try {
            dateFormat.parse(inDate.trim());
        } catch (ParseException pe) {
            return false;
        }
        return true;
    }

    /**
     *
     * @param day
     * @return
     */
    public boolean isValidDay(String day) {
        for (String elem : DAYS_OF_WEEK) {
            if (elem.equals(day)) {
                return true;
            }
        }
        return false;
    }

    /**
     *
     * @param cas
     * @return
     */
    public boolean isValidCas(String cas) {
        int hour = Integer.valueOf(cas.substring(0, 2));
        int minutes = Integer.valueOf(cas.substring(3));
        if (hour >= 0 && hour <= 24 && minutes >= 0 && minutes <= 60) {
            return true;
        }
        return false;
    }

    private int getIDzamestnanca(String menopriez, Zamestnanci zamestnanci) {
        if (menopriez.indexOf(" ") == -1) {
            return -1;
        }
        String meno = menopriez.substring(0, menopriez.indexOf(" "));
        String priezvisko = menopriez.substring(menopriez.indexOf(" ") + 1);
        for (Map.Entry<Integer, Zamestnanec> elem : zamestnanci.getZamestnanciAll().entrySet()) {
            int id = elem.getKey();
            Zamestnanec zam = elem.getValue();
            if (zam.getMeno().equals(meno) && zam.getPriezvisko().equals(priezvisko)) {
                return id;
            }
        }
        return -1;
    }

    public boolean importSviatky(String subor) throws ParseException, SQLException {
        ArrayList<Sviatok> result = new ArrayList<>();
        try {
            CsvReader sviatky = new CsvReader(subor, ';');

            sviatky.readHeaders();

            int riadok = 1;
            while (sviatky.readRecord()) {
                riadok++;
                String date = sviatky.get("datum").trim();
                if (!isValidDate(date)) {
                    JOptionPane.showMessageDialog(window, "Neplatný dátum sviatku na riadku: " + riadok + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }
                // dd.MM.yyyy
                if (date.charAt(1) == '.') {
                    date = "0" + date;
                }

                if (date.charAt(4) == '.') {
                    date = date.substring(0, 3) + "0" + date.substring(3);
                }

                String popis = sviatky.get("popis").trim();
                Calendar datum = Calendar.getInstance();
                datum.set(Integer.valueOf(date.substring(6)), Integer.valueOf(date.substring(3, 5)) - 1, Integer.valueOf(date.substring(0, 2)));
                result.add(0, new Sviatok(datum, popis));
            }

            // synch s databazou = vymaz vsetky a pridaj len tie, ktore sa nasli v csv
            Sviatky sv = new Sviatky();
            sv.removeAll();
            for (int i = 0; i < result.size(); i++) {
                sv.addSviatok(result.get(i));
            }
            sviatky.close();

        } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(window, "Súbor sa nenašiel !", "Chyba", JOptionPane.ERROR_MESSAGE);
            return false;
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    /**
     *
     * @param subor
     * @param zamestnanci
     * @param roz
     * @return
     * @throws SQLException
     * @throws ParseException
     */
    public boolean importRozpis(String subor, Zamestnanci zamestnanci) throws SQLException, ParseException {
        Rozpis result = null;
        try {
            CsvReader rozpis = new CsvReader(subor, ';');

            rozpis.readHeaders();

            int riadok = 0;
            ArrayList<Sluzba> sluzby = null;
            while (rozpis.readRecord()) {
                if (riadok % 2 == 0) {
                    sluzby = new ArrayList<>();
                }

                String date = rozpis.get("datum").trim();
                if (!isValidDate(date)) {
                    JOptionPane.showMessageDialog(window, "Nesprávny dátum na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                // dd.MM.yyyy
                if (date.charAt(1) == '.') {
                    date = "0" + date;
                }

                if (date.charAt(4) == '.') {
                    date = date.substring(0, 3) + "0" + date.substring(3);
                }
                // vytvor rozpis pre dany rok a mesiac
                if (riadok == 0) {
                    result = new Rozpis(Integer.parseInt(date.substring(3, 5)), Integer.parseInt(date.substring(6)));
                }

                String den = rozpis.get("den").trim();
                if (!isValidDay(den)) {
                    JOptionPane.showMessageDialog(window, "Nesprávny deň na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                String cas = rozpis.get("cas").trim();
                if (cas.charAt(1) == ':') {
                    cas = "0" + cas;
                }
                System.out.println("cas: " + cas);
                if (!isValidCas(cas)) {
                    JOptionPane.showMessageDialog(window, "Nesprávny čas na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                // M

                String zamM1 = rozpis.get("M_1").trim();
                if ("".equals(zamM1)) {
                    JOptionPane.showMessageDialog(window, "Nevyplnený zamestnanec na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                String zamM2 = rozpis.get("M_2").trim();
                if ("".equals(zamM2)) {
                    JOptionPane.showMessageDialog(window, "Nevyplnený zamestnanec na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                int idm1 = getIDzamestnanca(zamM1, zamestnanci);
                int idm2 = getIDzamestnanca(zamM2, zamestnanci);
                if (idm1 == -1 || idm2 == -1) {
                    JOptionPane.showMessageDialog(window, "Neznámy zamestnanec na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }
                Sluzba m = new Sluzba(date + " " + cas, VRATNICE[0], idm1, idm2);
                sluzby.add(m);

                // F

                String zamF1 = rozpis.get("F_1").trim();
                if ("".equals(zamF1)) {
                    JOptionPane.showMessageDialog(window, "Nevyplnený zamestnanec na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                String zamF2 = rozpis.get("F_2").trim();
                if ("".equals(zamF2)) {
                    JOptionPane.showMessageDialog(window, "Nevyplnený zamestnanec na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                int idf1 = getIDzamestnanca(zamF1, zamestnanci);
                int idf2 = zamF2.equals("-") ? 0 : getIDzamestnanca(zamF2, zamestnanci);
                if (idf1 == -1 || idf2 == -1) {
                    JOptionPane.showMessageDialog(window, "Nenznámy zamestnanec na riadku: " + (riadok + 2) + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }
                Sluzba f = new Sluzba(date + " " + cas, VRATNICE[1], idf1, idf2);
                sluzby.add(f);

                // citaj este jeden riadok

                if (riadok % 2 == 1) {
                    result.getRozpis().put(Integer.parseInt(date.substring(0, 2)), sluzby);
                }
                riadok++;
            }

            rozpis.close();
            result.commitSluzby();


        } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(window, "Súbor sa nenašiel !", "Chyba", JOptionPane.ERROR_MESSAGE);
            return false;
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    /**
     *
     * @param subor
     * @param zamestnanci
     * @return
     */
    public boolean exportZamestnanci(String subor, TreeMap<Integer, Zamestnanec> zamestnanci) {

        try {
            // use FileWriter constructor that specifies open for writing from the beginning of file
            CsvWriter csvOutput = new CsvWriter(new FileWriter(subor, false), ';');

            //write out the header line
            csvOutput.write("id");
            csvOutput.write("meno");
            csvOutput.write("priezvisko");
            csvOutput.write("typ");
            csvOutput.write("vahovanie");
            csvOutput.write("pocet dni dovolenky");
            csvOutput.endRecord();
            for (Iterator<Entry<Integer, Zamestnanec>> it = zamestnanci.entrySet().iterator(); it.hasNext();) {
                Map.Entry<Integer, Zamestnanec> elem = it.next();
                int id = elem.getKey();
                Zamestnanec tmp = elem.getValue();
                csvOutput.write(String.valueOf(id));
                csvOutput.write((String) tmp.getMeno());
                csvOutput.write((String) tmp.getPriezvisko());
                csvOutput.write(TYP_ZAMESTNANCA[tmp.getTypZamestnanca()]);
                csvOutput.write(String.valueOf(tmp.getVahovanie()));
                csvOutput.write(String.valueOf(tmp.getPocetDniDovolenky()));
                csvOutput.endRecord();
            }
            csvOutput.close();
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    /**
     *
     * @param subor
     * @param sviatky
     * @return
     */
    public boolean exportSviatky(String subor, ArrayList<Sviatok> sviatky) {

        try {
            // use FileWriter constructor that specifies open for writing to the beginning of file
            CsvWriter csvOutput = new CsvWriter(new FileWriter(subor, false), ';');

            //write out the header line
            csvOutput.write("datum");
            csvOutput.write("popis");
            csvOutput.endRecord();

            // write sviatky
            for (int i = 0; i < sviatky.size(); i++) {
                Sviatok tmp = sviatky.get(i);
                csvOutput.write(tmp.getDatum());
                csvOutput.write((String) tmp.getPopis());
                csvOutput.endRecord();
            }
            csvOutput.close();
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    public boolean exportRozpis(String subor, Rozpis rozpis, Zamestnanci zamestnanci) {

        try {
            // use FileWriter constructor that specifies open for writing to the beginning of file
            CsvWriter csvOutput = new CsvWriter(new FileWriter(subor, false), ';');

            //write out the header line
            csvOutput.write("datum");
            csvOutput.write("den");
            csvOutput.write("cas");
            csvOutput.write("M_1");
            csvOutput.write("M_2");
            csvOutput.write("F_1");
            csvOutput.write("F_2");
            csvOutput.endRecord();

            // write sluzby

            for (Iterator<Map.Entry<Integer, ArrayList<Sluzba>>> it = rozpis.getRozpis().entrySet().iterator(); it.hasNext();) {
                Map.Entry<Integer, ArrayList<Sluzba>> item = it.next();

                if (item.getValue().size() != 4) {
                    JOptionPane.showMessageDialog(window, "Nesprávny počet služieb na deň " + item.getValue().get(0).getDatum() + " !", "Chyba", JOptionPane.ERROR_MESSAGE);
                    return false;
                }

                // denna

                csvOutput.write(item.getValue().get(0).getDatum()); // datum
                csvOutput.write(DAYS_OF_WEEK[item.getValue().get(0).getCalendar().get(Calendar.DAY_OF_WEEK) - 1]); // den v tyzdni
                csvOutput.write(item.getValue().get(0).getCas()); // cas doobeda
                for (int i = 1; i >= 0; i--) {
                    Sluzba tmp = item.getValue().get(i);
                    if (i == 1) {
                        System.out.println(tmp.getID_zam1() + " " + tmp.getID_zam2());
                        csvOutput.write(zamestnanci.getZamestnanec(tmp.getID_zam1()).getMeno() + " " + zamestnanci.getZamestnanec(tmp.getID_zam1()).getPriezvisko());
                        csvOutput.write(zamestnanci.getZamestnanec(tmp.getID_zam2()).getMeno() + " " + zamestnanci.getZamestnanec(tmp.getID_zam2()).getPriezvisko());
                    } else {
                        csvOutput.write(zamestnanci.getZamestnanec(tmp.getID_zam1()).getMeno() + " " + zamestnanci.getZamestnanec(tmp.getID_zam1()).getPriezvisko());
                        if(tmp.getID_zam2() == 0) {
                            csvOutput.write("-");
                        } else {
                            csvOutput.write(zamestnanci.getZamestnanec(tmp.getID_zam2()).getMeno() + " " + zamestnanci.getZamestnanec(tmp.getID_zam2()).getPriezvisko());
                        }
                    }
                }
                csvOutput.endRecord();

                // nocna

                csvOutput.write(item.getValue().get(0).getDatum()); // datum
                csvOutput.write(DAYS_OF_WEEK[item.getValue().get(0).getCalendar().get(Calendar.DAY_OF_WEEK) - 1]); // den v tyzdni
                csvOutput.write(item.getValue().get(POCET_SLUZIEB_ZA_DEN).getCas()); // cas noc
                for (int i = 3; i >= 2; i--) {
                    Sluzba tmp = item.getValue().get(i);
                    csvOutput.write(zamestnanci.getZamestnanec(tmp.getID_zam1()).getMeno() + " " + zamestnanci.getZamestnanec(tmp.getID_zam1()).getPriezvisko());
                    csvOutput.write(zamestnanci.getZamestnanec(tmp.getID_zam2()).getMeno() + " " + zamestnanci.getZamestnanec(tmp.getID_zam2()).getPriezvisko());
                }
                csvOutput.endRecord();
            }

            csvOutput.close();
        } catch (IOException e) {
            Logger.getLogger(ImportExportCSV.class.getName()).log(Level.SEVERE, null, e);
            JOptionPane.showMessageDialog(window, "Chyba  !", "Chyba", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        return true;
    }
}
